﻿using MHI.ScenarioManager.Interfaces;
using MHI.ScenarioManager.Data;
using WebFoundation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using MHI.Utility;
using WebFoundation.Settings;

namespace MHI.ScenarioManager.Business
{
    internal class ScenarioList : BaseWritableEntities<Scenario>, IScenarioList
    {
        private WFModule _module;
        private ScenarioQueryDAO _queryDao;
        private ScenarioWritingDAO _writeDao;

        public ScenarioList(ScenarioQueryDAO querydao, ScenarioWritingDAO writingDao, WFModule module)
            : base(querydao, writingDao)
        {
            this._queryDao = querydao;
            this._writeDao = writingDao;
            this._module = module;
        }

        public List<Scenario> GetTemplateScenarios()
        {
            return _queryDao.GetTemplateScenarios().ToList<Scenario>();
        }

        public List<Scenario> GetScenarioByModelType(enumScenarioType modelType)
        {
            return _queryDao.GetScenarioByModelType(modelType).ToList<Scenario>();
        }

        public List<Scenario> GetScenarioByModelSubType(string modelSubType)
        {
            return _queryDao.GetScenarioByModelSubType(modelSubType).ToList<Scenario>();
        }

        public List<Scenario> GetChildScenarioListByScenario(Guid scenarioId)
        {
            return _queryDao.GetChildScenarioByScenario(scenarioId).ToList<Scenario>();
        }

        public Scenario GetTemplateScenarioByScenario(Guid scenarioId)
        {
            Scenario scenario = this.Get(scenarioId);
            if (scenario == null)
            {
                return null;
            }
            if (scenario.Template == 1)
            {
                return scenario;
            }
            else
            {
                Guid parentScenarioId = scenario.InheritedScenario;
                return GetTemplateScenarioByScenario(parentScenarioId);
            }
        }

        private Scenario _CreateScenario(Scenario newScenario, Scenario parentScenario, string sProjectFile, bool bAsModelScenario, string sNewScenarioName, string subType, string sDescription)
        {
            Scenario item = new Scenario();
            try
            {
                string sNewScenarioCode = string.Empty;
                bool bFromModel = newScenario == null ? false : true;
                if (!bFromModel && !File.Exists(sProjectFile)) return null;
                sNewScenarioCode = GeneralFunc.Name2Code(sNewScenarioName);

                sNewScenarioCode = _queryDao.GetNewUniqueScenarioCode(sNewScenarioCode);
                Scenario newTBScenario = new Scenario();
                newTBScenario.Id = Guid.NewGuid();
                newTBScenario.ScenarioCode = sNewScenarioCode;
                newTBScenario.ScenarioName = sNewScenarioName;
                newTBScenario.CreateTime = DateTime.Now;
                Guid guid = _writeDao.Add(newTBScenario);
                if (guid == Guid.Empty) return null;

                string sNewPath = string.Empty;
                DateTime st = DateTime.Now;
                DateTime et = st;

                string workFolder = WFAppSettings.GetDefaultConfig().ReadValue(Scenario.WorkFolderAppSettingCode);
                if (workFolder != string.Empty)
                {
                    if (bAsModelScenario)
                    {
                        sNewPath = Path.Combine(workFolder,Scenario.TemplateFolderName);
                    }
                    else
                    {
                        sNewPath = Path.Combine(workFolder, Scenario.ScenarioFolderName);
                    }
                }
                string sNewScenarioPath = Path.Combine(sNewPath, sNewScenarioCode);

                if (Directory.Exists(sNewScenarioPath))
                {
                    DirectoryInfo pDir = new DirectoryInfo(sNewScenarioPath);
                    sNewScenarioCode = pDir.Name;
                }

                Directory.CreateDirectory(sNewScenarioPath);
                DirectoryInfo pNewPath = new DirectoryInfo(sNewScenarioPath);

                FileInfo pFile = null;
                string sType = "";
                enumScenarioType eScenarioType = enumScenarioType.Unknown;
                DirectoryInfo pSourcePath = null;
                DirectoryInfo pIniFilesPath1 = null;

                if (bFromModel)
                {
                    sType = newScenario.ModelType.ToString();
                    sProjectFile = newScenario.ProjectFile;
                    st = newScenario.StartTime;
                    et = newScenario.EndTime;
                }
                else
                {
                    pFile = new FileInfo(sProjectFile);
                    sProjectFile = pFile.Name;
                    string sExt = pFile.Extension.ToUpper();
                    if (sExt == ".INP")
                    {
                        if (!File.Exists(pFile.FullName.Replace(pFile.Extension, ".mdb")))
                        {
                            eScenarioType = enumScenarioType.SWMMModel;
                        }
                        else
                        {
                            eScenarioType = enumScenarioType.InpWDModel;
                        }
                        sType = eScenarioType.ToString();
                        pIniFilesPath1 = pNewPath;
                    }
                    else if (sExt == ".XAJ")
                    {
                        eScenarioType = enumScenarioType.XAJ11Model;
                        sType = eScenarioType.ToString();
                        pIniFilesPath1 = pNewPath;
                    }
                    else if (sExt == ".XLSX")
                    {
                        eScenarioType = enumScenarioType.WaterForecastModel;
                        sType = eScenarioType.ToString();
                        pIniFilesPath1 = pNewPath;
                    }
                    pSourcePath = new DirectoryInfo(pFile.Directory.FullName);
                }

                Scenario updateTBScenario = _queryDao.Get(guid);

                updateTBScenario.ModelSubType = subType.ToString();
                if (newScenario != null)
                {
                    updateTBScenario.InheritedScenario = newScenario.Id;
                    if (subType == string.Empty)
                    {
                        updateTBScenario.ModelSubType = newScenario.ModelSubType;
                    }
                }
                updateTBScenario.RelativeFolder = sNewScenarioCode;
                updateTBScenario.Description = sDescription;
                updateTBScenario.Template = bAsModelScenario ? 1 : 0;
                updateTBScenario.ProjectFile = sProjectFile;
                updateTBScenario.ModelType = sType;
                updateTBScenario.AutoAmend = 1;
                updateTBScenario.OnlineFirst = 1;
                updateTBScenario.Enabled = 1;
                updateTBScenario.StartTime = st;
                updateTBScenario.CurrentTime = st;
                updateTBScenario.EndTime = et;
                //updateTBScenario.ModelSubType = subType.ToString();

                if (_writeDao.Update(updateTBScenario))
                {
                    item = updateTBScenario;
                }
            }
            catch(Exception ex)
            {
                this.GetType().LogError("Failed to create scenario", ex);
                item = null;
            }
            return item;
        }

        public Scenario GetScenario(string scenarioCode)
        {
            return _queryDao.GetScenarioByCode(scenarioCode);
        }

        public Scenario CreateScenario(Scenario newScenario, Scenario parentScenario, string sProjectFile, bool bAsModelScenario, string sNewScenarioName, string subType, string sDescription)
        {
            return _CreateScenario(newScenario, parentScenario, sProjectFile, bAsModelScenario, sNewScenarioName, subType, sDescription);
        }

        public Scenario CreateScenario(string sProjectFile, bool bAsModelScenario, string sNewScenarioName, string subType, string sDescription)
        {
            return _CreateScenario(null, null, sProjectFile, bAsModelScenario, sNewScenarioName, subType, sDescription);
        }

        public Scenario CreateScenario(Scenario newScenario, Scenario parentScenario, bool bAsModelScenario, string sNewScenarioName, string subType, string sDescription)
        {
            return _CreateScenario(newScenario, parentScenario, string.Empty, bAsModelScenario, sNewScenarioName, subType, sDescription);
        }

        public Scenario CreateScenario(Scenario newScenario, bool bAsModelScenario, string sNewScenarioName, string subType, string sDescription)
        {
            return _CreateScenario(newScenario, null, string.Empty, bAsModelScenario, sNewScenarioName, subType, sDescription);
        }

        public Scenario Copy(Scenario org, string nameName)
        {
            return _CreateScenario(org, org, string.Empty, false, nameName, org.ModelSubType, org.Description);
        }

        public bool DeleteScenarioByCode(string scenarioCode)
        {
            Scenario item = _queryDao.GetScenarioByCode(scenarioCode);
            if (item != null)
            {
                return _writeDao.Delete(item);
            }
            return false;
        }

        public Scenario Rename(string scenarioCode, string newScenarioName)
        {
            Scenario item = new Scenario();
            item = _queryDao.GetScenarioByCode(scenarioCode);
            if (item != null)
            {
                item.ScenarioName = newScenarioName;
                if (!_writeDao.Update(item))
                {
                    return null;
                }
            }
            return item;
        }


        public bool IsCalculated(string scenarioCode)
        {
            Scenario item = new Scenario();
            item = _queryDao.GetScenarioByCode(scenarioCode);
            if (item != null)
            {
                return Convert.ToBoolean(item.Calculated);
            }
            return false;
        }
    }
}
